package com.bianmaba.sso.configure;

import com.bianmaba.commons.bean.result.OperationResult;
import com.bianmaba.commons.utils.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

/**
 * @author Shenluw
 * 创建日期：2018/3/21 15:02
 */
@Configuration
@EnableAuthorizationServer
public class CustomAuthorizationServerConfigurerAdapter extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()")
                .allowFormAuthenticationForClients();
        security.authenticationEntryPoint((request, response, e) -> {
            OperationResult result = OperationResult.of(false, "资源请求失败，非法的访问凭证（access token）！")
                    .setStatus(401, (Integer) null, HttpStatus.valueOf(401)
                            .getReasonPhrase());
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setStatus(401);
            ResponseUtil.writeJson(response, result);
        });
        security.accessDeniedHandler((request, response, e) -> {
            OperationResult result = OperationResult.of(false, "资源请求失败，当前用户没有取得该资源的授权，请联系管理员授权！")
                    .setStatus(403, null, HttpStatus.valueOf(403).getReasonPhrase());
            response.setStatus(403);
            ResponseUtil.writeJson(response, result);
        });
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("testclient")
                .secret("{noop}testclient")
                .scopes("test")
                .authorizedGrantTypes("client_credentials", "password", "authorization_code", "refresh_token", "implicit")
                .redirectUris("http://192.168.0.11:6002/login", "http://192.168.0.11:6003/login")
                .resourceIds("order")
                .autoApprove(true).accessTokenValiditySeconds(60);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
        endpoints.tokenStore(memoryTokenStore());
        endpoints.accessTokenConverter(jwtAccessTokenConverter());
        endpoints.tokenStore(jwtTokenStore());
        endpoints.exceptionTranslator(new CustomWebResponseExceptionTranslator());
    }

    public static class CustomWebResponseExceptionTranslator implements WebResponseExceptionTranslator {
        @Override
        public ResponseEntity translate(Exception e) {
            if (OAuth2Exception.class.isAssignableFrom(e.getClass())) {
                OAuth2Exception oAuth2Exception = (OAuth2Exception) e;
                OperationResult result = OperationResult.of(false, "资源请求失败，" + oAuth2Exception.getLocalizedMessage() + "，请联系管理员授权！");
                result.setStatus(oAuth2Exception.getHttpErrorCode(), oAuth2Exception.getLocalizedMessage());
                ResponseEntity response = new ResponseEntity(result, HttpStatus.valueOf(oAuth2Exception.getHttpErrorCode()));
                return response;
            } else {
                OperationResult result = OperationResult.of(false, "资源请求失败，认证失败，请联系管理员授权！");
                result.setStatus(400, "Bad Request");
                ResponseEntity response = new ResponseEntity(result, HttpStatus.valueOf(400));
                return response;
            }
        }
    }

    @Bean
    public TokenStore memoryTokenStore() {
        return new InMemoryTokenStore();
    }


    @Bean
    public JwtTokenStore jwtTokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new BianmabaJwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey("cjs");   //  Sets the JWT signing key
        return jwtAccessTokenConverter;
    }
}
